package main
import (
	"fmt"
	"reflect"	
)


type User struct {
	Id int
	Name string
	Age int
}
func (this *User) Call(){
	fmt.Println("id:",this.Id)
	fmt.Println("name:",this.Name)
	fmt.Println("age:",this.Age)
}

func reflectNum(arg interface{}){
	fmt.Println("type of arg :",reflect.TypeOf(arg))
	// fmt.Printf("type of arg :%T\n",arg)
	fmt.Println("value of arg :",reflect.ValueOf(arg))
}

func DoFiledAndMethod(input interface{}){
	inputType := reflect.TypeOf(input)
	fmt.Println("input type:",inputType.Name())
	inputValue := reflect.ValueOf(input)
	fmt.Println("input value:",inputValue)
	fmt.Println("======================")

	// 通过type获取字段
	for  i := 0;  i < inputType.NumField();  i++ {
		field := inputType.Field(i)
		value := inputValue.Field(i).Interface()
		fmt.Printf("%v %v = %v\n",field.Type,field.Name,value)
	}

	// 通过value获取方法
	// 注意：go 1.17之后NumMethod不可用 
	for i := 0; i < inputType.NumMethod(); i++ {
		fmt.Println("in")
		m := inputType.Method(i)
		fmt.Printf("%v %v\n",m.Name,m.Type)
	}
}

func main(){
	var num float64 = 3.1415
	reflectNum(num)

	user := User{1,"alan",24}
	user.Call()
	DoFiledAndMethod(user)

}	